from typing import List, Optional
# 移除直接导入,改为延迟导入
# # # # from User_Management.user_classes import Teacher, Student  # 延迟导入  # 延迟导入  # 延迟导入
# from Assignment_and_Grading.course_task_classes import AbstractAssignable

class Course:
    # 类变量:存储所有课程实例
    _all_courses = []
    
    #课程类,管理课程信息、学生名单和作业
    
    def __init__(self, course_id: str, course_name: str, teacher: object,  # 改为object类型
                 max_students: int = 30, course_description: str = "", status: str = "pending"):
        # 添加教师参数验证
        if teacher is None:
            raise ValueError("Course must have an associated teacher")
        
        # 封装课程核心属性(私有属性通过getter/setter访问)
        self._course_id = course_id
        self._course_name = course_name
        self._teacher = teacher  # 关联Teacher对象
        self._max_students = max_students
        self._course_description = course_description
        self._status = status  # 添加状态属性,默认为pending
        self.enrolled_students: List[object] = []  # 改为object类型
        self.course_assignments: List[object] = []  # 改为object类型
        
        # 将新创建的课程实例添加到类变量中
        Course._all_courses.append(self)

    # 添加状态属性的访问器
    @property
    def status(self) -> str:
        return self._status
    
    @status.setter
    def status(self, value: str) -> None:
        self._status = value


    # 静态方法:从数据加载所有课程
    @staticmethod
    def load_all_courses(courses_data: List[dict]) -> None:
        """从数据字典列表加载所有课程
        
        Args:
            courses_data: 课程数据字典列表
        """
        Course._all_courses.clear()  # 清空现有课程
        
        # 延迟导入
        from User_Management.user_classes import User
        
        for course_data in courses_data:
            # 直接从当前的course_data获取课程信息
            course_id = course_data.get('course_id')
            course_name = course_data.get('course_name')
            course_description = course_data.get('course_description', '')
            max_students = course_data.get('max_students', 30)
            status = course_data.get('status', 'pending')
            
            # 支持从'teacher_id'和'teacher'两个字段获取教师ID
            teacher_id = course_data.get('teacher_id', course_data.get('teacher', None))
            
            if not all([course_id, course_name]):
                continue
            
            # 查找对应的教师对象
            teacher = None
            if teacher_id:
                for user in User.all_users():
                    # 优先匹配teacher_id,其次匹配user_id作为后备方案
                    if hasattr(user, 'teacher_id') and user.teacher_id == teacher_id or user.user_id == teacher_id:
                        teacher = user
                        break
            
            # 创建课程实例 - 注意参数名要与构造函数一致
            course = Course(
                course_id=course_id,  # 直接使用course_id值,不是字典
                course_name=course_name,  # 直接使用course_name值,不是字典
                teacher=teacher,
                max_students=max_students,
                course_description=course_description,  # 参数名应该是course_description,不是description
                status=status
            )

    # 添加assignment相关方法时再导入AbstractAssignable
    def add_assignment(self, assignment: object) -> bool:
        """添加作业到课程"""
        try:
            if not hasattr(self, 'course_assignments'):
                self.course_assignments = []
        
            # 避免重复添加
            if assignment.assignable_id not in [a.assignable_id for a in self.course_assignments]:
                self.course_assignments.append(assignment)
            
                # 标记数据变更并保存
                if hasattr(self, 'lms') and self.lms:
                    self.lms.mark_data_changed()
                    self.lms.save_data()
                return True, "作业发布成功"
            else:
                return False, "作业已存在"
        except Exception as e:
            return False, f"作业发布失败: {str(e)}"


    # 静态方法:获取所有课程实例
    @staticmethod
    def all_courses() -> List['Course']:
        """返回所有课程实例的列表"""
        return Course._all_courses.copy()

    # 封装:属性访问器(避免直接修改敏感数据)
    @property
    def course_id(self) -> str:
        return self._course_id

    @property
    def course_name(self) -> str:
        return self._course_name
    
    @course_name.setter
    def course_name(self, value: str) -> None:
        if value and isinstance(value, str):
            self._course_name = value

    @property
    def max_students(self) -> int:
        return self._max_students

    @max_students.setter
    def max_students(self, value: int) -> None:
        if isinstance(value, int) and value > 0:
            self._max_students = value

    @property
    def teacher(self) -> Optional[object]:
        # 延迟导入
        from User_Management.user_classes import Teacher

        return self._teacher
    
    @teacher.setter
    def teacher(self, value: Optional[object]) -> None:
        # 延迟导入
        from User_Management.user_classes import Teacher
        self._teacher = value
    
    @property
    def course_description(self) -> str:
        return self._course_description
    
    @course_description.setter
    def course_description(self, value: str) -> None:
        if isinstance(value, str):
            self._course_description = value

    @property
    def current_enrollment(self) -> int:
        return len(self.enrolled_students)


    def remove_assignment(self, assignment: object) -> bool:
        try:
            if hasattr(self, 'course_assignments'):
                original_length = len(self.course_assignments)
                self.course_assignments = [a for a in self.course_assignments if a.assignable_id != assignment.assignment_id]
            
                if len(self.course_assignments) < original_length:
                    # 标记数据变更并保存
                    if hasattr(self, 'lms') and self.lms:
                        self.lms.mark_data_changed()
                        self.lms.save_data()
                    return True, "作业删除成功"
            return False, "作业不存在"
        except Exception as e:
            return False, f"作业删除失败: {str(e)}"

    # 学生选课状态管理
    def get_enrolled_students(self) -> List[object]:
        # 延迟导入
        from User_Management.user_classes import Student
        #返回已选课学生列表(副本,避免外部直接修改)
        return self.enrolled_students.copy()

    def check_enrollment_status(self, student: object) -> bool:
        # 延迟导入
        from User_Management.user_classes import Student
        #检查学生是否已选该课程
        return student in self.enrolled_students

    # 内部方法:仅允许选课系统修改学生列表(封装保护)
    def _add_student(self, student: object) -> bool:
        #添加学生到课程(私有方法,由选课系统调用)
        # 延迟导入
        from User_Management.user_classes import Student
        if self.current_enrollment >= self._max_students:
            return False
        if self.check_enrollment_status(student):
            return False
        self.enrolled_students.append(student)
        return True

    def _remove_student(self, student: object) -> bool:
        # 延迟导入
        from User_Management.user_classes import Student
        #移除学生从课程(私有方法,由选课系统调用)
        if not self.check_enrollment_status(student):
            return False
        self.enrolled_students.remove(student)
        return True

    def __str__(self) -> str:
        teacher_name = self._teacher.username if self._teacher else "未分配"
        return (f"Course ID: {self._course_id} | Name: {self._course_name} | "
                f"Teacher: {teacher_name} | Capacity: {self.current_enrollment}/{self._max_students}")

# 测试代码
if __name__ == "__main__":
    # 创建模拟的教师和学生对象进行测试
    class MockTeacher:
        def __init__(self, username):
            self.username = username
            self.name = username  # 添加name属性
            
    class MockStudent:
        def __init__(self, username):
            self.username = username
            
    # 使用模拟对象进行测试
    teacher = MockTeacher("张老师")
    student1 = MockStudent("学生A")
    student2 = MockStudent("学生B")
    
    # 创建课程
    course = Course("CS101", "计算机科学导论", teacher, 2, "计算机科学基础课程")
    
    # 测试私有方法(仅用于演示,实际应该通过选课系统调用)
    print("测试私有方法(仅用于演示):")
    success1 = course._add_student(student1)
    print(f"添加学生1: {'成功' if success1 else '失败'}")
    
    success2 = course._add_student(student2)
    print(f"添加学生2: {'成功' if success2 else '失败'}")
    
    # 测试已选课学生列表
    enrolled_students = course.get_enrolled_students()
    print(f"已选课学生数量: {len(enrolled_students)}")
    
    # 测试选课状态检查
    status1 = course.check_enrollment_status(student1)
    status2 = course.check_enrollment_status(student2)
    print(f"学生1选课状态: {'已选' if status1 else '未选'}")
    print(f"学生2选课状态: {'已选' if status2 else '未选'}")
    
    # 显示课程信息(使用__str__方法)
    print("\n课程信息:")
    print(course)
    
    # 测试退课功能
    success_remove = course._remove_student(student1)
    print(f"移除学生1: {'成功' if success_remove else '失败'}")
    
    # 显示更新后的课程信息
    print("\n更新后的课程信息:")
    print(course)
    
    print("课程管理模块测试完成!")